package cn.foolishbird.crow.core.util;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * @author foolish bird
 * @email luohongtu@foolishbird.cn
 */
public final class ReflectUtils {

    private ReflectUtils() {

    }


    /**
     * 递归修改某个类型属性
     *
     * @param object    对象
     * @param filter    过滤器
     * @param convertor 转换器
     * @throws IllegalAccessException 异常
     */
    public static void recursiveTransformation(Object object, Class<?> clz, Predicate<Field> filter, Function<FieldInfo, Object> convertor) throws IllegalAccessException {
        if (Objects.isNull(object) || Objects.isNull(clz)) {
            return;
        }

        //  判断本身是不是数组
        if (clz.isArray()) {
            Object[] objects = (Object[]) object;
            if (ArrayUtils.isNotEmpty(objects)) {
                for (Object obj : objects) {
                    if (Objects.nonNull(obj)) {
                        recursiveTransformation(obj, obj.getClass(), filter, convertor);
                    }
                }
            }
        }
        if (Collection.class.isAssignableFrom(clz)) {
            Collection<?> collection = (Collection<?>) object;
            if (CollectionUtils.isNotEmpty(collection)) {
                for (Object obj : collection) {
                    if (Objects.nonNull(obj)) {
                        recursiveTransformation(obj, obj.getClass(), filter, convertor);
                    }
                }
            }
        }
        if (Map.class.isAssignableFrom(clz)) {
            Map map = (Map) object;
            for (Object k : map.keySet()) {
                recursiveTransformation(k, k.getClass(), filter, convertor);
            }
            for (Object v : map.values()) {
                recursiveTransformation(v, v.getClass(), filter, convertor);
            }
        }

        Field[] fields = clz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if (field.getClass().isArray()) {
                Object[] objects = (Object[]) field.get(object);
                if (ArrayUtils.isNotEmpty(objects)) {
                    for (Object obj : objects) {
                        if (Objects.nonNull(obj)) {
                            recursiveTransformation(obj, obj.getClass(), filter, convertor);
                        }
                    }
                }
            }
            if (Collection.class.isAssignableFrom(field.getType())) {
                Collection<?> collection = (Collection<?>) field.get(object);
                if (CollectionUtils.isNotEmpty(collection)) {
                    for (Object obj : collection) {
                        if (Objects.nonNull(obj)) {
                            recursiveTransformation(obj, obj.getClass(), filter, convertor);
                        }
                    }
                }
            }
            if (Map.class.isAssignableFrom(field.getType())) {
                Map map = (Map) field.get(object);
                for (Object k : map.keySet()) {
                    recursiveTransformation(k, k.getClass(), filter, convertor);
                }
                for (Object v : map.values()) {
                    recursiveTransformation(v, v.getClass(), filter, convertor);
                }
            }

            if (filter.test(field)) {
                FieldInfo info = new FieldInfo();
                info.setObject(object);
                info.setField(field);
                field.set(object, convertor.apply(info));
            }
        }

        // 递归调用父类
        recursiveTransformation(object, clz.getSuperclass(), filter, convertor);
    }


}
